#ifndef _IM_SERVER_MESSAGE_ADAPTER_
#define _IM_SERVER_MESSAGE_ADAPTER_

#include "MessageService.h"

#include "im/common/common.h"
#include "melon/client/thrift_client_pool.h"
#include "melon/client/zk_service_locator.h"
#include "base/singleton.h"

namespace imserver {

#define MESSAGE_SERVER_KEY "/im/message_service/v1/shard_0"

using melon::client::ClientPool;

class MessageAdapter : public base::Singleton<MessageAdapter> {
public:

  int CreateMessage(std::map<int64_t, int64_t>& _return, const ImMessage& message, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      MessageServiceClient * client = pool_.Alloc(MESSAGE_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("MessageAdapter::CreateMessage --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->CreateMessage(_return, message);
      } catch (const std::exception & e) {
        LOG_ERROR("MessageAdapter::CreateMessage --> err. error:" << e.what() << " retry:" << i);
        success = false;
      }
      pool_.Release(MESSAGE_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

  int SetMessageReceiveStatus(int64_t uid, int64_t msg_id, int64_t dialogue_id, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      MessageServiceClient * client = pool_.Alloc(MESSAGE_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("MessageAdapter::SetMessageReceiveStatus --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->SetMessageReceiveStatus(uid, msg_id, dialogue_id);
      } catch (const std::exception & e) {
        LOG_ERROR("MessageAdapter::SetMessageReceiveStatus --> err. error:" << e.what() << " uid:" << uid <<
            " msg_id:" << msg_id << " dialogue_id:" << dialogue_id << " retry:" << i);
        success = false;
      }
      pool_.Release(MESSAGE_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

  int SetMessageReadStatus(int64_t uid, int64_t msg_id, int64_t dialogue_id, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      MessageServiceClient * client = pool_.Alloc(MESSAGE_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("MessageAdapter::SetMessageReadStatus --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->SetMessageReadStatus(uid, msg_id, dialogue_id);
      } catch (const std::exception & e) {
        LOG_ERROR("MessageAdapter::SetMessageReadStatus --> err. error:" << e.what() << " uid:" << uid <<
            " msg_id:" << msg_id << " dialogue_id:" << dialogue_id << " retry:" << i);
        success = false;
      }
      pool_.Release(MESSAGE_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

private:
  friend class base::Singleton<MessageAdapter>;

  MessageAdapter() : pool_(300) {
    ConfigReader cfg("../conf/rpc_adapters.conf");
    std::string default_location(cfg.Get("message_service", "service_list"));
    pool_.set_default_location(default_location);

    ConfigReader zk_cfg("../conf/zookeeper.conf");
    if (!zk_cfg) {
      LOG_WARN("Config file ../conf/zookeeper.conf read error!");
      return;
    }
    pool_.set_locator(new melon::client::ZkServiceLocator(zk_cfg.Get("zookeeper", "service_registry").c_str()));
  }


  ClientPool<MessageServiceClient> pool_;
};

}

#endif // _IM_SERVER_MESSAGE_ADAPTER_
